﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Apollo;

namespace AlgoMF
{
    public class AlgoMFOrder : ApolloComplexOrder, IApolloTradingListener
    {
        ApolloOrder entryOrder = null;
        private AlgoMFContract priContract;
        private AlgoMFContract subContract;
        private AlgoMFStrategy mfStrategy;

        public AlgoMFOrder(string parentName, string name, long qty, long price, ApolloOrderDirection direct, AlgoMFContract contractInfo, AlgoMFContract priContract, AlgoMFStrategy strategy)
            :base(contractInfo.getTrader(), parentName, name, contractInfo.getInstrId(), contractInfo.getProductInfo())
        {
            this.quantity = qty;
            this.price = price;
            this.direction = direct;
            this.subContract = contractInfo;
            this.priContract = priContract;
            this.mfStrategy = strategy;
        }

        public override void onApolloRtnOrder(ApolloOrderField order, ApolloExchangeEventContext context)
        {
            if (order.status == ApolloOrderStatus.AllTraded && order.instrumentId == priContract.getInstrId())
            {
                entryOrder = null;
                reject();
            }
        }

        public override void onApolloRtnTrade(ApolloTradeField trade, ApolloExchangeEventContext context)
        {
            ApolloGlobal.getCore().debugPrint("------AlgoMF onApolloRtnTrade orderRef=[{0}] instr=[{1}] volume=[{2}]------", trade.orderRef, trade.instrumentId, trade.volume);
            if (trade.instrumentId == subContract.getInstrId())
            {
                if (trade.direction == ApolloOrderDirection.Buy)
                {
                    long hedgeVol = mfStrategy.hedgeQty(subContract.getInstrId(), subContract.getRatio(), this.quantity, trade.volume, trade.orderRef, trade.direction, this.price);
                    long price = this.price + (priContract.getSellThrd() - subContract.getBuyThrd()) - priContract.getProductInfo().TickValue; 
                    ApolloGlobal.getCore().debugPrint("------在原买单方向有成交, 成交量=[{0}] 本次对冲量=[{1}] 对冲价格=[{2}]------", trade.volume, hedgeVol, price);
                    if (hedgeVol == 0)
                    {
                        return;
                    }
                    entryOrder = ApolloOrder.createOrder(priContract.getTrader(), parentName, name, priContract.getInstrId(), priContract.getProductInfo(), hedgeVol, price, ApolloOrderDirection.Sell);
                    entryOrder.addTradingListener(this);
                    trader.getFront().getOrderProcessor().putInsertOrder(entryOrder);
                }
                else
                {
                    long hedgeVol = mfStrategy.hedgeQty(subContract.getInstrId(), subContract.getRatio(), this.quantity, trade.volume, trade.orderRef, trade.direction, this.price);
                    long price = trade.price + (priContract.getBuyThrd() - subContract.getSellThrd()) + priContract.getProductInfo().TickValue;
                    ApolloGlobal.getCore().debugPrint("------在原卖单方向有成交, 成交量=[{0}] 本次对冲量=[{1}] 对冲价格=[{2}]------", trade.volume, hedgeVol, price);
                    entryOrder = ApolloOrder.createOrder(priContract.getTrader(), parentName, name, priContract.getInstrId(), priContract.getProductInfo(), hedgeVol, price, ApolloOrderDirection.Buy);
                    entryOrder.addTradingListener(this);
                    trader.getFront().getOrderProcessor().putInsertOrder(entryOrder);
                }
            }
        }

        public override bool isRegularOrder()
        {
            return false;
        }

        public override bool isSupportedFront(ApolloFront front)
        {
            return true;
        }

        protected override bool rejectHandler()
        {
            if (entryOrder != null)
            {
                entryOrder.removeTradingListener(this);
                trader.getFront().getOrderProcessor().putCancelOrder(entryOrder);
            }
            return true;
        }

        protected override bool submitHandler()
        {
            entryOrder = ApolloOrder.createOrder(trader, parentName, name, instrumentId, productInfo, quantity, price, direction);
            entryOrder.addTradingListener(this);
            trader.getFront().getOrderProcessor().putInsertOrder(entryOrder);
            return true;
        }

    }
}

